#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys, os, types, tempfile, subprocess, re, getpass, random
import tfsbuild

def _escapeArg(arg):
    return arg.replace('"', r'\"')

def _joinArgv(argv):
    cmdstr = ""
    for arg in argv:
        if (' ' in arg or '*' in arg) and arg[0] != '/':
            cmdstr += '"%s"' % _escapeArg(arg)
        elif arg[0] != '/':
            cmdstr += _escapeArg(arg)
        else:
            cmdstr += arg
        cmdstr += ' '
    if cmdstr.endswith(' '): cmdstr = cmdstr[:-1]  # strip trailing space
    return cmdstr

_hook_fun = None
def _run(argv):
    exefile = argv[0]
    exefile = os.path.abspath(exefile)
    exeshort = os.path.basename(exefile)
    args = _joinArgv([exeshort] + argv[1:])
    p = subprocess.Popen(args, bufsize=-1,executable=exefile,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    output = p.stdout.read()
    error = p.stderr.read()
    retval = p.wait()
    return output, error, retval

class tfclient(object):
    def __init__(self,path=r'C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\tf.exe',
                 userpass=[],
                 collection=r'http://tfs.autodesk.com:8080/tfs/AcadCollection'):
        def is_exe(fpath):
            return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
        if not is_exe(path):
            raise Exception("tf.exe is not found")
        self.path = path
        self.collection = collection
        self.opts = {"noprompt": None}
        if userpass != None and len(userpass) == 2:
            self.opts.update(login='{},{}'.format(*userpass))
    def genopt(self, **opts):
        for key, value in opts.iteritems():
            yield "/{}:{}".format(key,value) if value!=None else "/{}".format(key)
    def _tfrun(self, cmd, *args, **kargs):
        cmdline = [self.path, cmd]
        cmdline += self.genopt(**self.opts)
        cmdline += self.genopt(**kargs)
        cmdline += args
        return _run(cmdline)
    def workspaces(self):
        data = self._tfrun("workspaces", collection=self.collection)[0]
        wks = data.splitlines()[3:]
        wks = [i.split()[0] for i in wks]
        return wks
    def create_workspace(self, name, path):
        pdir = os.path.abspath(path)
        if os.path.isfile(pdir): raise Exception("%s is not a folder." % pdir)
        if not os.path.isdir(pdir):
            os.makedirs(pdir)
        data = self._tfrun('workspace', name, new=None, collection=self.collection)[0]
        data = self._tfrun('workfold', '$/', pdir, workspace=name, map=None)[0]
    def del_workspace(self, name):
        return self._tfrun('workspace', name, delete=None, collection=self.collection)[0]
    def sync(self, *files):
        data = self._tfrun('get',*files, version='T')[0]
    def co(self, *files):
        data = self._tfrun('checkout',*files)[0]
    def ci(self, note, *files):
        data = self._tfrun('checkin', *files,comment=note)[0]
        return data
    def shelve(self,name,note,*files):
        data = self._tfrun('shelve',name,*files,comment=note)
        return data
    def history(self, file, max = 3):
        data = self._tfrun('history', file, recursive=None, stopafter=max)[0]
        history = data.splitlines()[2:]
        history = [ item.split(None, 5) for item in history ]
        return history
    def setworkspace (self, name):
        self.opts.update(workspace=name)
    


def build_op(file):
    data = open(file,'r+').read()
    data = re.sub(r'((?:ACADV_BLDMINOR|HEIDI_BLDMINOR_VERSION)\s+)(\d+)', lambda m: m.group(1) + str(long(m.group(2)) + 1) , data)
    try:
        open(file,'w+').write(data)
        major = re.search(r'ACADV_BLDMAJOR\s+(\d+)',data).group(1)
        stream = re.search(r'ACADV_BLDSTREAM\s+(\S)',data).group(1)
        minor = re.search(r'ACADV_BLDMINOR\s+(\d+)',data).group(1)
        branch = re.search(r'ACADV_BLDBRANCH\s+(\S)',data).group(1)
    except Exception:
        return None
    return (stream,long(major),branch,long(minor))

def parse_r(data):
    ss = re.search(r'Changeset\s+#(\d+)\s+checked',data)
    if ss and ss.group(1):
        return ss.group(1)
    return None

def incre_build(stream, host):
    tfc = tfclient()
    pdir = tempfile.mkdtemp()
    wname = '{}_tfb{}'.format(getpass.getuser(),random.randint(1000,9999))
    data = tfc.create_workspace(wname,pdir)
    file1 = '/AutoCAD/M-Branches/{}/components/global/src/heidi/source/heidi/_version.h'.format(stream)
    file2 = '/AutoCAD/M-Branches/{}/components/global/src/objectdbx/inc/_idver.h'.format(stream)
    file1 = pdir+ file1
    file2 = pdir + file2
    data = tfc.sync(file1, file2)
    data = tfc.co(file1, file2)
    build_op(file1)
    info = build_op(file2)
    data = tfc.ci('"Increment Build ID to {}{:03}{}{:02}"'.format(*info),file1,file2)
    tfc.del_workspace(wname)
    os.system('rmdir /S /Q "{}"'.format(pdir))
    print(data)
    syncat = parse_r(data)
    if syncat:
        tfsbuild.trigger(stream,'DAILY', syncat, host)

def main(argv):
    from optparse import OptionParser
    parser = OptionParser("Usage: %prog [options] <branch>")
    parser.add_option("-u", "--user", action="store", type="string", metavar='<user name>', help='build forge user name')
    parser.add_option("-p", "--password", action="store", type="string", metavar='<password>', help='build forge password')
    parser.add_option("-s", "--bfserver", action="store", type="string", default='usecspdbforge', metavar='<build forge server>', help='build forge server')
    
    options, args = parser.parse_args(argv)
    if not args or len(args) != 1:
        parser.print_help()
        sys.exit(1)
    if options.user and options.password:
        tfsbuild.user = options.user
        tfsbuild.password = options.password
    else:
        print("Invalid Credentials")
        sys.exit(1)
    incre_build(args[0].upper(), options.bfserver)

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))